﻿namespace RagSharpCore.Service
{
	using System;
	using System.Collections.Generic;
	using System.Net.Http;
	using System.Text;
	using System.Text.Json;
	using System.Text.Json.Serialization;
	using System.Threading.Tasks;

	public class EmbeddingService : IDisposable
	{
		private readonly HttpClient _httpClient;
		private readonly string _embeddingUrl = "http://10.193.40.136:8099/sepd_llm_app/v1/embedding_model";
		private bool _disposedValue; // 用于检测重复调用Dispose

		// 初始化HttpClient（建议在应用启动时创建一次，避免频繁销毁）
		public EmbeddingService(string embeddingUrl = "")
		{
			if (embeddingUrl != "") _embeddingUrl = embeddingUrl;

			_httpClient = new HttpClient();
			// 设置超时时间（根据服务响应速度调整）
			_httpClient.Timeout = TimeSpan.FromSeconds(30);
			// 设置默认请求头（如Content-Type）
			_httpClient.DefaultRequestHeaders.Accept.Add(
				new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(
					"application/json")
			);
		}

		/// <summary>
		/// 调用向量化服务，生成文本向量
		/// </summary>
		/// <param name="texts">需要生成向量的文本列表</param>
		/// <param name="model">可选：指定模型名称</param>
		/// <returns>生成的向量列表</returns>
		public async Task<List<List<float>>?> GetEmbeddingsAsync(
			List<string> texts,
			 //string? model = null,
			 bool isDense = true,
			string? authToken = null  // 可选：如果服务需要认证
		)

		{
			var defaultRes = new List<List<float>>() { };

			try
			{
				// 1. 构造请求体
				var requestBody = new EmbeddingRequest
				{
					texts = texts,
					//Model = model
				};

				// 2. 序列化请求体为JSON
				string jsonBody = JsonSerializer.Serialize(requestBody, new JsonSerializerOptions
				{
					PropertyNamingPolicy = JsonNamingPolicy.CamelCase  // 匹配JSON的驼峰命名
				});
				using var content =
					new StringContent(jsonBody, Encoding.UTF8, "application/json");

				// 3. 如果需要认证，添加Authorization头
				if (!string.IsNullOrEmpty(authToken))
				{
					_httpClient.DefaultRequestHeaders.Authorization =
						new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken);
				}

				// 4. 发送POST请求
				HttpResponseMessage response = await _httpClient.PostAsync(_embeddingUrl, content);

				// 5. 检查响应是否成功（HTTP 200-299）
				response.EnsureSuccessStatusCode();

				// 6. 读取响应内容并反序列化为对象
				string responseJson = await response.Content.ReadAsStringAsync();
				var embeddingResponse = JsonSerializer.Deserialize<EmbeddingResponse>(
					responseJson,
					new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
				);

				if (embeddingResponse == null) { return defaultRes; }
				if (isDense)
				{
					return embeddingResponse.embeddings.Select(ed => ed.embedDense).ToList();
				}
				else
				{
					return embeddingResponse.embeddings.Select(ed => ed.embedSparse).ToList();
				}
			}
			catch (HttpRequestException ex)
			{
				// 处理HTTP错误（如连接失败、状态码4xx/5xx）
				Console.WriteLine($"HTTP请求失败：{ex.Message}");
				return defaultRes;
			}
			catch (JsonException ex)
			{
				// 处理JSON序列化/反序列化错误
				Console.WriteLine($"JSON解析失败：{ex.Message}");
				return defaultRes;
			}
			catch (Exception ex)
			{
				// 处理其他异常
				Console.WriteLine($"向量化服务调用失败：{ex.Message}");
				return defaultRes;
			}

		}

		// ------------------------------
		// 实现IDisposable接口释放资源（解决CA1001）
		// ------------------------------
		protected virtual void Dispose(bool disposing)
		{
			if (!_disposedValue)
			{
				if (disposing)
				{
					// 释放托管资源（HttpClient）
					_httpClient?.Dispose();
				}

				// 释放非托管资源（如果有）
				_disposedValue = true;
			}
		}

		// 析构函数：用于释放非托管资源（如果有）
		~EmbeddingService()
		{
			Dispose(disposing: false);
		}

		// 公开的Dispose方法，供外部调用
		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this); // 告诉GC不需要再调用析构函数
		}
	}


	// 请求模型（发送给服务的参数）
	public class EmbeddingRequest
	{
		// 需要生成向量的文本列表（必填）
		[JsonPropertyName("texts")]
		public List<string> texts { get; set; } = new List<string>();

		//// 可选：指定使用的模型（如果服务支持）
		//[JsonPropertyName("model")]
		//public string? Model { get; set; }
	}

	// 响应模型（服务返回的结果）
	public class EmbeddingResponse
	{

		// 生成的向量列表（每个元素是一个文本的向量数组）
		[JsonPropertyName("embeddings")]
		public List<Embedding> embeddings { get; set; } = new List<Embedding>();

		// 向量维度
		[JsonPropertyName("dense_dim")]
		public int dimension { get; set; }


	}

	public class Embedding
	{
		[JsonPropertyName("dense")]
		public List<float> embedDense { get; set; } = new List<float>();

		[JsonPropertyName("sparse")]
		public List<float> embedSparse { get; set; } = new List<float>();

	}

	public class Demo
	{
		void Test()
		{
			//// 使用 using 语句声明，确保对象使用后自动调用 Dispose 释放资源
			//using var embedClient = new EmbeddingServiceClient();
			//// 后续使用 embedClient 调用方法...
			//var texts = new List<string> { "测试文本1", "测试文本2" };
			//var embeddings = await embedClient.GetEmbeddingsAsync(texts);
			//var spare_embeddings = await embedClient.GetEmbeddingsAsync(texts, false);
			//List<ReadOnlyMemory<float>> searchVectors =
			//	new List<ReadOnlyMemory<float>>() { embeddings![0].ToArray() };
			//var outputFields = new List<string>() { "describ" };
			//var searchResults = await MilvusOrm.instance.SearchBy(
			//	vectorFieldName: "describ_dense",
			//	 searchVectors: searchVectors,
			//	 expr: "",
			//	 outputFields: outputFields);
		}
	}

}
